package com.qingcloud.adminbackend.utils;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.cell.CellEditor;
import cn.hutool.poi.excel.editors.TrimEditor;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.File;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;

/**
 * 导出Excel文档工具类
 *
 * @author liyubai
 * @date 2017-01-03
 */
public class ExcelUtil {

    /**
     * 通用获取Cell字段值
     *
     * @param cell
     * @return
     * @Title: getCellValue
     * @author liyubai
     * @date 2017年1月6日
     */
    public static String getCellValue(Cell cell) {
        DecimalFormat df = new DecimalFormat("#0.0000");
        String cellValue = null;
        if (cell == null)
            return null;
        CellType cellType = cell.getCellType();
        if (cellType == CellType.NUMERIC) {
            if (HSSFDateUtil.isCellDateFormatted(cell)) {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                cellValue = sdf.format(HSSFDateUtil.getJavaDate(cell.getNumericCellValue()));
            } else {
                cellValue = df.format(cell.getNumericCellValue());
            }
        } else if (cellType == CellType.STRING) {
            cellValue = String.valueOf(cell.getStringCellValue());
        } else if (cellType == CellType.FORMULA) {
            cellValue = String.valueOf(cell.getCellFormula());
        } else if (cellType == CellType.BOOLEAN) {
            cellValue = String.valueOf(cell.getBooleanCellValue());
        } else if (cellType == CellType.ERROR) {
            cellValue = String.valueOf(cell.getErrorCellValue());
        } else {
            cellValue = null;
        }
        if (cellValue != null && cellValue.trim().length() <= 0) {
            cellValue = null;
        }
        return cellValue;
    }


    /**
     * 通用获取Cell字段值
     *
     * @param cell
     * @return
     * @Title: getCellValue
     * @author liyubai
     * @date 2017年1月6日
     */
    public static String getCellValueNew(XSSFCell cell) {
        String cellValue = null;
        if (cell == null)
            return null;
        if (cell.getCellType() == CellType.NUMERIC) {
            cellValue = cell.getRawValue();
        } else {
            cellValue = cell.getStringCellValue();
        }
        return cellValue;
    }


    /**
     * 获取数字类型的单元格值
     *
     * @param cell 单元格
     * @return 单元格值，可能为Long、Double、Date
     */
    private static Object getNumericValue(Cell cell) {
        final double value = cell.getNumericCellValue();

        final CellStyle style = cell.getCellStyle();
        if (null == style) {
            return value;
        }

        final short formatIndex = style.getDataFormat();
        final String format = style.getDataFormatString();

        // 判断是否为日期
        if (isDateType(formatIndex, format)) {
            return DateUtil.date(cell.getDateCellValue());// 使用Hutool的DateTime包装
        }

        // 普通数字
        if (null != format && format.indexOf(StrUtil.C_DOT) < 0) {
            final long longPart = (long) value;
            if (longPart == value) {
                // 对于无小数部分的数字类型，转为Long
                return longPart;
            }
        }
        return value;
    }

    /**
     * 获取单元格值
     *
     * @param cell            {@link Cell}单元格
     * @param cellType        单元格值类型{@link }枚举
     * @param isTrimCellValue 如果单元格类型为字符串，是否去掉两边空白符
     * @return 值，类型可能为：Date、Double、Boolean、String
     */
    public static Object getCellValue(Cell cell, CellType cellType, final boolean isTrimCellValue) {
        return getCellValue(cell, cellType, isTrimCellValue ? new TrimEditor() : null);
    }

    /**
     * 获取单元格值
     *
     * @param cell            {@link Cell}单元格
     * @param isTrimCellValue 如果单元格类型为字符串，是否去掉两边空白符
     * @return 值，类型可能为：Date、Double、Boolean、String
     */
    public static String getCellValue(Cell cell, boolean isTrimCellValue) {
        return getCellValue(cell, cell.getCellType(), isTrimCellValue).toString();
    }

    /**
     * 获取单元格值(字符串类型)
     *
     * @param cell {@link Cell}单元格
     * @return 值类型String
     */
    public static String getCellStringValue(Cell cell) {
        if (cell == null) {
            return StrUtil.EMPTY;
        }
        Object object = getCellValue(cell, cell.getCellType(), true);
        if (object != null) {
            return object.toString().trim();
        }
        return StrUtil.EMPTY;
    }


    /**
     * 获取单元格值<br>
     * 如果单元格值为数字格式，则判断其格式中是否有小数部分，无则返回Long类型，否则返回Double类型
     *
     * @param cell       {@link Cell}单元格
     * @param cellType   单元格值类型{@link }枚举，如果为{@code null}默认使用cell的类型
     * @param cellEditor 单元格值编辑器。可以通过此编辑器对单元格值做自定义操作
     * @return 值，类型可能为：Date、Double、Boolean、String
     */
    public static Object getCellValue(Cell cell, CellType cellType, CellEditor cellEditor) {
        if (null == cell) {
            return null;
        }


        Object value;
        if (cellType == CellType.NUMERIC) {
            value = getNumericValue(cell);
        } else if (cellType == CellType.BOOLEAN) {
            value = cell.getBooleanCellValue();
        } else if (cellType == CellType.FORMULA) {
            // 遇到公式时查找公式结果类型
            value = getCellValue(cell, cell.getCachedFormulaResultType(), cellEditor);
        } else if (cellType == CellType.BLANK) {
            value = StrUtil.EMPTY;
        } else {
            value = cell.getStringCellValue();
        }
        return null == cellEditor ? value : cellEditor.edit(cell, value);
    }


    /**
     * 是否为日期格式<br>
     * 判断方式：
     *
     * <pre>
     * 1、指定序号
     * 2、org.apache.poi.ss.usermodel.DateUtil.isADateFormat方法判定
     * </pre>
     *
     * @param formatIndex 格式序号
     * @param format      格式字符串
     * @return 是否为日期格式
     */
    private static boolean isDateType(int formatIndex, String format) {
        // yyyy-MM-dd----- 14
        // yyyy年m月d日---- 31
        // yyyy年m月------- 57
        // m月d日 ---------- 58
        // HH:mm----------- 20
        // h时mm分 -------- 32
        if (formatIndex == 14 || formatIndex == 31 || formatIndex == 57 || formatIndex == 58 || formatIndex == 20 || formatIndex == 32) {
            return true;
        }

        if (org.apache.poi.ss.usermodel.DateUtil.isADateFormat(formatIndex, format)) {
            return true;
        }

        return false;
    }

    /**
     * NULL转空字符串
     *
     * @param str
     * @return
     * @Title: nullToString
     * @author liyubai
     * @date 2017年1月13日
     */
    public String nullToString(String str) {
        if (str == null) {
            return "";
        } else {
            return str;
        }
    }

}
